﻿// ==============================================================================
// Copyright (c) 2012 Bndy.Net, All rights reserved.
// Created by Bndy on 3/21/2012 9:49:29 PM
//
//                    * * * * * * * * * * * * * 
//                    * MAIL- bndy5337@163.com *       http://www.bndy.net
//                    * Q Q - 81795705 =========================================>
//                    * MSN - bndy5337@msn.com *
//                    * * * * * * * * * * * * * 
//
// ------------------------------------------------------------------------------
// 
// ==============================================================================

using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Text;

namespace Net.Bndy.Web.Controls
{
    public class DataTable<TItem> where TItem : class
    {
        public string Id { get; set; }
        public List<Column> Columns { get; set; }
        public bool HideHeader { get; set; }
        public IEnumerable<TItem> DataSource { get; set; }
        public object Attributes { get; set; }

        private const string TEMPLATE_TABLE = "<table id=\"{0}\" name=\"{0}\" {3}>{1}<tbody>{2}</tbody></table>";
        private const string TEMPLATE_TABLE_HEADER = "<thead><tr>{0}</tr></thead>";
        private const string TEXT_NO_DATA = "No Data Found.";

        public DataTable(string id, params Column[] columns)
        {
            this.Id = id;
            this.Columns = columns.ToList();
        }

        public string ToHtml()
        {
            string result = string.Empty;

            string header = string.Empty;
            string body = string.Empty;
            List<string> attributes = new List<string>();

            if (!this.HideHeader)
                header = BuildHeader();

            body = BuildBody();

            if (this.Attributes != null)
            {
                foreach (PropertyInfo pi in Attributes.GetType().GetProperties())
                {
                    attributes.Add(string.Format("{0}=\"{1}\"", pi.Name,
                        pi.GetValue(this.Attributes, null))
                        );
                }
            }
            return string.Format(TEMPLATE_TABLE, this.Id, header, body,
                string.Join(" ", attributes.ToArray())
                );
        }

        private string BuildHeader()
        {
            StringBuilder sb = new StringBuilder();

            foreach (Column c in this.Columns)
            {
                string htmlHeader = null;
                if (c.AllowSort)
                {
                    string url = UrlHelper.SetQueryString(
                        "direct",
                        UrlHelper.GetQueryString("direct").Equals("asc", StringComparison.OrdinalIgnoreCase)
                            ? "desc" : "asc",
                        UrlHelper.SetQueryString("sort", c.BoundItemNames[0])
                        );

                    htmlHeader = string.Format("<a href=\"{0}\">{1}</a>",
                        url,
                        c.HeaderText);
                }
                else
                {
                    htmlHeader = c.HeaderText;
                }
                sb.AppendFormat("<th>{0}</td>", htmlHeader);
            }

            return string.Format(TEMPLATE_TABLE_HEADER, sb.ToString());
        }

        private string BuildBody()
        {
            StringBuilder sb = new StringBuilder();

            if (this.DataSource == null || this.DataSource.Count() == 0)
            {
                sb.AppendFormat("<tr><td colspan=\"{0}\">{1}</td></tr>",
                    this.Columns.Count,
                    TEXT_NO_DATA);
            }
            else
            {
                // Sorts the Data in the Data Layer.

                foreach (TItem item in DataSource)
                {
                    sb.Append("<tr>");
                    foreach (Column c in this.Columns)
                    {
                        string data = string.Empty;
                        List<object> items = new List<object>();

                        foreach (string name in c.BoundItemNames)
                        {
                            object value = item.GetType().GetProperty(name).GetValue(item, null);

                            if (value == null)
                                items.Add(string.Empty);
                            else
                                items.Add(value);
                        }

                        if (c.DataHandler != null)
                        {
                            data = c.DataHandler(items.ToArray());
                        }
                        else
                        {
                            data = string.Format(c.DataFormat ?? "{0}", items.ToArray());
                        }

                        sb.AppendFormat("<td>{0}</td>", data);
                    }
                    sb.Append("</tr>");
                }
            }

            return string.Format(TEMPLATE_TABLE_HEADER, sb.ToString());
        }

        public class Column
        {
            public string HeaderText { get; set; }
            public bool AllowSort { get; set; }
            public string DataFormat { get; set; }
            public string[] BoundItemNames { get; set; }
            public Func<object[], string> DataHandler { get; set; }
        }
    }
}
